package com.tang.multi.v2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author Tang
 * @classname Rector
 * @description [  ]
 * @date 2021/8/10 13:58
 */
public class Rector implements Runnable {

    private ServerSocketChannel serverSocketChannel;

    /**
     * 监听连接
     */
    private Selector selector;

    public Rector(int port) throws Exception {
        this.serverSocketChannel = ServerSocketChannel.open();
        this.serverSocketChannel.configureBlocking(false);
        this.serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", port));
        this.serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 128);
        this.selector = Selector.open();
        SelectionKey selectionKey = this.serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
        // 附加 Acceptor
        selectionKey.attach(new Acceptor(this.serverSocketChannel));
    }

    @Override
    public void run() {
        while (true) {
            try {
                this.selector.select();
                Set<SelectionKey> selectionKeys = this.selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    dispatch(selectionKey);
                    iterator.remove();
                }
                selectionKeys.clear();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void dispatch(SelectionKey selectionKey) {
        Runnable runnable = (Runnable) selectionKey.attachment();
        runnable.run();
    }

}